package org.jaaksi.commondemo.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

public class MultiLauncher extends ViewGroup {
  private static final int SNAP_VELOCITY = 500;
  private Scroller mScroller;
  private int touchSlop;    //最小滑动距离，超过了，才认为开时滑动
  private static final String TAG = "MultiLauncher";
  private static final int TOUCH_STATE_STOP = 0x001;    //停止状态
  private static final int TOUCH_STATE_FLING = 0x002;    //滑动状态
  private int touchState = TOUCH_STATE_STOP;
  private float lastionMotionX = 0;            //上次触摸屏的x位置
  private int curScreen;                    //当前屏
  private VelocityTracker velocityTracker;    //速率跟踪器

  public MultiLauncher(Context context) {
    super(context);
  }

  public MultiLauncher(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public MultiLauncher(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mScroller = new Scroller(context);
    touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
  }

  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    measureChildren(widthMeasureSpec, heightMeasureSpec);
    int width = measureWidth(widthMeasureSpec);
    int height = measureHeight(heightMeasureSpec);
    setMeasuredDimension(width, height);
  }

  private int measureHeight(int heightMeasureSpec) {
    int mode = MeasureSpec.getMode(heightMeasureSpec);
    int size = MeasureSpec.getSize(heightMeasureSpec);

    int height = 0;
    if (mode == MeasureSpec.AT_MOST) {
      throw new IllegalStateException("Must not be" + " MeasureSpec.AT_MOST.");
    } else {
      height = size;
    }
    return height;
  }

  private int measureWidth(int widthMeasureSpec) {
    int mode = MeasureSpec.getMode(widthMeasureSpec);
    int size = MeasureSpec.getSize(widthMeasureSpec);

    int width = 0;
    if (mode == MeasureSpec.AT_MOST) {
      throw new IllegalStateException("Must not be" + " MeasureSpec.AT_MOST.");
    } else {
      width = size;
    }
    return width * this.getChildCount();
  }

  @Override protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int n = this.getChildCount();
    int w = (r - l) / n;
    int h = b - t;

    for (int i = 0; i < n; i++) {
      View child = getChildAt(i);
      int left = i * w;
      int right = (i + 1) * w;
      int top = 0;
      int bottom = h;

      child.layout(left, top, right, bottom);
    }
  }

  public void moveToScreen(int whichScreen) {
    curScreen = whichScreen;
    if (curScreen > getChildCount() - 1) {
      curScreen = getChildCount() - 1;
    }
    if (curScreen < 0) {
      curScreen = 0;
    }
    int scrollX = getScrollX();
    int splitWidth = getWidth() / getChildCount();    //每一屏的宽度
    int dx = curScreen * splitWidth - scrollX;        //要移动的距离
    mScroller.startScroll(scrollX, 0, dx, 0, Math.abs(dx));//开始移动
    invalidate();
  }

  public void moveToDestination() {
    int splitWidth = getWidth() / getChildCount();    //每一屏的宽度
    int toScreen = (getScrollX() + splitWidth / 2) / splitWidth;//判断是回滚还是进入下一屏
    moveToScreen(toScreen);            //移动到目标分屏
  }

  public void moveToNext() {
    moveToScreen(curScreen + 1);
  }

  public void moveToPrevious() {
    moveToScreen(curScreen - 1);
  }

  @Override public boolean onInterceptTouchEvent(MotionEvent ev) {
    int action = ev.getAction();
    final int x = (int) ev.getX();
    if (action == MotionEvent.ACTION_MOVE && touchState == TOUCH_STATE_STOP) {
      return true;
    }
    switch (action) {
      case MotionEvent.ACTION_DOWN:
        lastionMotionX = x;
        touchState = mScroller.isFinished() ? TOUCH_STATE_STOP : TOUCH_STATE_FLING;
        break;
      case MotionEvent.ACTION_MOVE:
        //滑动距离过小不算滑动
        final int dx = (int) Math.abs(x - lastionMotionX);
        if (dx > touchSlop) {
          touchState = TOUCH_STATE_FLING;
        }
        break;
      case MotionEvent.ACTION_CANCEL:
      case MotionEvent.ACTION_UP:
        touchState = TOUCH_STATE_STOP;
        break;
      default:
        break;
    }
    return touchState != TOUCH_STATE_STOP;
  }

  @Override public boolean onTouchEvent(MotionEvent event) {
    if (velocityTracker == null) {
      velocityTracker = VelocityTracker.obtain();
    }
    velocityTracker.addMovement(event);
    super.onTouchEvent(event);

    int action = event.getAction();
    final int x = (int) event.getX();
    switch (action) {
      case MotionEvent.ACTION_DOWN:
        //手指按下时，如果正在滚动，则立即停止
        if (mScroller != null && !mScroller.isFinished()) {
          mScroller.abortAnimation();
        }
        lastionMotionX = x;
        break;
      case MotionEvent.ACTION_MOVE:
        //随手指滑动
        int dx = (int) (lastionMotionX - x);
        scrollBy(dx, 0);
        lastionMotionX = x;
        break;
      case MotionEvent.ACTION_UP:
        final VelocityTracker velocityTracker = this.velocityTracker;
        velocityTracker.computeCurrentVelocity(1000);
        int velocityX = (int) velocityTracker.getXVelocity();
        //通过velocityX的正负值可以判断滑动方向
        if (velocityX > SNAP_VELOCITY && curScreen > 0) {
          moveToPrevious();
        } else if (velocityX < -SNAP_VELOCITY && curScreen < (getChildCount() - 1)) {
          moveToNext();
        } else {
          moveToDestination();
        }
        if (velocityTracker != null) {
          this.velocityTracker.clear();
          this.velocityTracker.recycle();
          this.velocityTracker = null;
        }
        touchState = TOUCH_STATE_STOP;
        break;
      case MotionEvent.ACTION_CANCEL:
        touchState = TOUCH_STATE_STOP;
        break;
    }
    return true;
  }

  @Override public void computeScroll() {
    if (mScroller.computeScrollOffset()) {
      this.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
      postInvalidate();
    }
  }
}